﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "../xos/head.h"
#include "../os/head.h"
#include "../os/uuid.h"
#include "misc_impl.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos
{
    ////////////////////////////////////////////////////////////////////////////////////
    // 

    static misc_impl::POOL * pool_ptr = 0;

    ////////////////////////////////////////////////////////////////////////////////////
    //

    misc_impl::misc_impl()
    {
    }

    misc_impl::~misc_impl()
    {
        term();
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    int misc_impl::get_addr( POOL *** pppPool, LIST *** pppList )
    {
        int ret = 0;
        if( pppPool )
        {
            *pppPool = &pool_ptr;
        }
        if( pppList )
        {
            *pppList = 0;
        }
        return ret;
    }

    int misc_impl::init()
    {
        int nRet = 0;
        return nRet;
    }

    int misc_impl::term()
    {
        int nRet = 0;
        return nRet;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // utf8 to wchar
    // 
    int misc_impl::utf8_to_wchar( const char * lpszSrc, int nSrcByteSize, wchar_t * lpszDest, int nDestByteSize, int * lpnDestNeedSize )
    {
        int nRet = 0;
        return nRet;
    }

    // 
    // wcharto utf8
    // 
    int misc_impl::wchar_to_utf8( const wchar_t * lpszSrc, int nSrcByteSize, char * lpszDest, int nDestByteSize, int * lpnDestNeedSize )
    {
        int nRet = 0;
        return nRet;
    }

    // 
    // utf8 to ansi
    // 
    int misc_impl::utf8_to_ansi( const char * lpszSrc, int nSrcByteSize, char * lpszDest, int nDestByteSize, int * lpnDestNeedSize )
    {
        int nRet = 0;

        if( lpnDestNeedSize )
        {
            *lpnDestNeedSize = nSrcByteSize + 1;
        }

        if( nSrcByteSize < nDestByteSize )
        {
            strcpy( lpszDest, lpszSrc );
        }
        else
        {
            nRet = 1;
        }

        return nRet;
    }

    // 
    // ansi utf8
    // 
    int misc_impl::ansi_to_utf8( const char * lpszSrc, int nSrcByteSize, char * lpszDest, int nDestByteSize, int * lpnDestNeedSize )
    {
        int nRet = 0;

        if( lpnDestNeedSize )
        {
            *lpnDestNeedSize = nSrcByteSize + 1;
        }

        if( nSrcByteSize < nDestByteSize )
        {
            strcpy( lpszDest, lpszSrc );
        }
        else
        {
            nRet = 1;
        }

        return nRet;
    }

    // 
    // get process full file name
    // 
    int misc_impl::get_process_file_full_name( char * pszFile, int nLen, int * pnLenNeeded )
    {
        int nRet = 0;

        char szFile[4096] = { 0 };
        int len = 0;

        os::get_exe_full_file( szFile, sizeof( szFile ) / sizeof( szFile[0] ) );

        len = strlen( szFile ) + 1;

        if( pszFile && ( nLen > len ) )
        {
            strcpy( pszFile, szFile );
        }

        if( pnLenNeeded )
        {
            *pnLenNeeded = len + 1;
        }

        return nRet;
    }

    // 
    // get process file path. including '\\' or '/'
    //
    int misc_impl::get_process_path( char * pszPath, int nLen, int * pnLenNeeded )
    {
        int nRet = 0;

        char szFile[4096] = { 0 };

        os::get_exe_full_file( szFile, sizeof( szFile ) / sizeof( szFile[0] ) );

        char * p = 0, * pp = szFile;

        while( *pp != 0 )
        {
            if( *pp == '/' )
            {
                p = pp;
            }

            ++pp;
        }

        if( p )
        {
            *p = 0;
        }

        int len = ( int )strlen( szFile );

        if( pnLenNeeded )
        {
            *pnLenNeeded = len;
        }

        if( pszPath && ( nLen > len ) )
        {
            strcpy( pszPath, szFile );
        }
        else
        {
            nRet = 1;
        }

        return nRet;
    }

    // 
    // get real path.
    // 
    int misc_impl::real_path( const char * lpszPath, char * lpszRealPath, int nSize )
    {
        int ret = 0;
        const char * lpszRet = 0;
        if( lpszRealPath )
        {
            lpszRet = realpath( lpszPath, lpszRealPath );
        }
        if( !lpszRet )
        {
            ret = 1;
        }
        return ret;
    }

    // 
    // append path in all platform
    // 
    int misc_impl::path_append( char * lpszPath, const char * lpszAdder )
    {
        int nRet = 0;

        size_t tLen = strlen( lpszPath );

        if( 0 == nRet )
        {
            if( ( tLen > 0 ) && ( *( lpszPath + tLen - 1 ) != '/' ) )
            {
                strcat( lpszPath, "/" );
            }

            strcat( lpszPath, lpszAdder );
        }

        return nRet;
    }

    // 
    // url append
    // 
    int misc_impl::url_append( char * lpszUrl, const char * lpszAdder )
    {
        int nRet = 0;

        size_t tLen = strlen( lpszUrl );

        if( 0 == nRet )
        {
            if( ( tLen > 0 ) && ( *( lpszUrl + tLen ) != '/' ) )
            {
                strcat( lpszUrl, "/" );
            }

            strcat( lpszUrl, lpszAdder );
        }

        return nRet;
    }

    // 
    // create guid
    // 
    int misc_impl::create_guid( char * lpszGuid )
    {
        int nRet = 0;

        if( lpszGuid )
        {
            uuid_t uuid = { 0 };
            uuid_generate( uuid );
            uuid_unparse_lower( uuid, lpszGuid );
        }

        return nRet;
    }

    // 
    // sleep 1 / 1000 second
    // 
    int misc_impl::sleep( int nMilliseconds )
    {
        int nRet = 0;
        usleep( 1000 * nMilliseconds );
        return nRet;
    }

    // 
    // output debuf info
    // 
    int misc_impl::out_put_debug_string( const char * lpszInfo )
    {
        int nRet = 0;
        return nRet;
    }

    int misc_impl::out_put_to_cmd( const char * lpszInfo )
    {
        using namespace std;
        int nRet = 0;
        cout << lpszInfo << endl;
        return nRet;
    }

    int misc_impl::trace( const char * lpszFormat, ... )
    {
        using namespace std;

        int nRet = 0;

        const int N = 1024 * 100;
        char buf[N] = { 0 };

        va_list  va;
        va_start( va, lpszFormat );
        nRet = vsnprintf( buf, N, lpszFormat, va );
        va_end( va );

        cout << buf << endl;

        return nRet;
    }

    // 
    // get seconds from since 1970-1-1
    // 
    xos_u64 misc_impl::get_wall_second( xos_u64 * lpWallSecond )
    {
        xos_u64 xRet = ( xos_u64 )time( 0 );
        *lpWallSecond = xRet;
        return xRet;
    }

    // 
    // get process ID
    // 
    xos_u64 misc_impl::get_current_process_id()
    {
        xos_u64 xRet = 0;
        return xRet;
    }

    // 
    // get thread ID
    // 
    xos_u64 misc_impl::get_current_thread_id()
    {
        xos_u64 xRet = ( xos_u64 )pthread_self();
        return xRet;
    }

    const char * misc_impl::platform()
    {
        return os::platform();
    }

    bool misc_impl::can_hot_replace()
    {
        return os::can_hot_replace();
    }

    // 
    // get cpu num
    // 
    int misc_impl::get_cpu_num()
    {
        int nNum = 1;
        int nRet = 0;

        const int N = 100 * 1024;
        char buf[N] = { 0 };
        int nLen = 0;

        FILE * fp = 0;

        if( 0 == nRet )
        {
            fp = fopen( "/proc/cpuinfo", "rb" );

            if( !fp )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            nLen = fread( buf, 1, N, fp );

            fclose( fp );
            fp = 0;

            if( nLen <= 0 )
            {
                nRet = 1;
            }
            else
            {
                buf[nLen] = 0;
            }
        }

        if( 0 == nRet )
        {
            int n = 0;
            const char * p = buf;

            while( 1 )
            {
                p = ::strstr( p, "processor" );

                if( p )
                {
                    p++;
                    n++;
                }
                else
                {
                    break;
                }
            }

            if( n > 0 )
            {
                nNum = n;
            }
        }

        return nNum;
    }
} // xos
